#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "cmsis_os2.h"
#include "ohos_init.h"
#include "cJSON.h"
#include "iot_pwm.h"
#include <dtls_al.h>
#include <mqtt_al.h>
#include <oc_mqtt_al.h>
#include <oc_mqtt_profile.h>
#include "iot_i2c.h"
#include "iot_i2c_ex.h"
#include "iot_gpio.h"
#include "iot_gpio_ex.h"
#include "wifi_sta_connect.h"
#include "motor.h"
#include "Init.h"
#include "temp_humi.h"

#define IOT_GPIO_KEY 5
#define I2C_SDA_GPIO_IDX 13
#define I2C_SCL_GPIO_IDX 14
#define SHT30_ADDR 0x44
#define WIFI_IOT_I2C_IDX_0 0
#define LED_GPIO_IDX 6
#define CONFIG_APP_DEVICEID "1234abcdcxy"
#define CONFIG_APP_DEVICEPWD "123456789"
#define CONFIG_APP_SERVERIP "220c8efaf7.iot-mqtts.cn-north-4.myhuaweicloud.com"
#define CONFIG_APP_SERVERPORT "1883"
#define CONFIG_APP_LIFETIME 60

#define WIFI_SSID "Mi"     // 修改为自己的WiFi 热点账号
#define WIFI_PWD "88888888" // 修改为自己的WiFi 热点密码

enum MotorState
{
    motor_0 = 0,
    motor_1 = 1,
    motor_2 = 2,
    motor_3 = 3,
};

enum MotorState motor_state = motor_0;

typedef struct
{
    int temp;
    int hum;
} report_t;

int led_control(int onoff)
{
    IoTGpioSetOutputVal(LED_GPIO_IDX, onoff ? 1 : 0);
}

void msg_rcv_callback(oc_mqtt_profile_msgrcv_t *payload)
{
    printf("payload is %s,request_id = %s\n", payload->msg, payload->request_id);

    cJSON *root = cJSON_Parse(payload->msg);
    if (root == NULL)
    {
        printf(">>>>>>>>>>>root = NULL\n");
        return;
    }
    cJSON *cmd_name_obj = cJSON_GetObjectItem(root, "command_name");
    if (cmd_name_obj)
    {
        printf(">>>>>>>>>>>cmd_name_obj is true\n");
        char *command_name = cJSON_GetStringValue(cmd_name_obj);
        // int *speed_level=cJSON_GetNumberValue(cmd_name_obj);
        if (command_name != NULL)
        {
            printf(">>>>>>>>>>>command_name != NULL\n");
            if (strcmp(command_name, "led_control") == 0)
            {
                printf(">>>>>>>>>>>command_name is led_control\n");
                cJSON *paras_obj = cJSON_GetObjectItem(root, "paras");
                if (paras_obj != NULL)
                {
                    printf(">>>>>>>>>>>paras_obj !=NULL\n");
                    cJSON *led_obj = cJSON_GetObjectItem(paras_obj, "LED");
                    if (led_obj != NULL)
                    {
                        printf(">>>>>>>>>>>led_obj != NULL\n");
                        char *led_cmd_str = cJSON_GetStringValue(led_obj);
                        if (strcmp(led_cmd_str, "ON") == 0)
                        {
                            // led turn on
                            led_control(1); //------------------
                            printf(" led turn on\n");
                        }
                        else if (strcmp(led_cmd_str, "OFF") == 0)
                        {
                            led_control(0); //------------------
                            printf(" led turn off\n");
                            // led turn off
                        }
                    }
                }
            }
            else if (strcmp(command_name, "motor_control") == 0)
            {
                printf(">>>>>>>>>>>command_name is motor_control\n");
                cJSON *paras_obj = cJSON_GetObjectItem(root, "paras");
                if (paras_obj != NULL)
                {
                    printf(">>>>>>>>>>>paras_obj !=NULL\n");
                    cJSON *motor_obj = cJSON_GetObjectItem(paras_obj, "motor_onoff");
                    cJSON *motor_lev = cJSON_GetObjectItem(paras_obj, "motor_level");
                    if (motor_obj != NULL)
                    {
                        printf(">>>>>>>>>>>motol_obj != NULL\n");
                        char *motor_cmd_str = cJSON_GetStringValue(motor_obj);
                        if (strcmp(motor_cmd_str, "ON") == 0)
                        {
                            int motor_level = cJSON_GetNumberValue(motor_lev);
                            if (motor_level == 1)
                            {
                                motor_state = motor_1;
                                // motor turn on
                                motor_control(1); //------------------
                                printf(" motor turn on,the speed is level 1\n");
                            }
                            else if (motor_level == 2)
                            {
                                motor_state = motor_2;
                                // motor turn on
                                motor_control(2); //------------------
                                printf(" motor turn on,the speed is level 2\n");
                            }
                            else if (motor_level == 3)
                            {
                                motor_state = motor_3;
                                // motor turn on
                                motor_control(3); //------------------
                                printf(" motor turn on,the speed is level 3\n");
                            }
                        }
                        else if (strcmp(motor_cmd_str, "OFF") == 0)
                        {
                            motor_state = motor_0;
                            motor_control(0); //------------------
                            printf(" motor turn off\n");
                            // led turn off
                        }
                    }
                }
            }
        }
    }
    cJSON_Delete(root);
}

static void deal_report_msg(report_t *report)
{
    oc_mqtt_profile_service_t service;

    oc_mqtt_profile_kv_t humi_property;
    oc_mqtt_profile_kv_t temp_property;

    humi_property.key = "humi";
    humi_property.value = &report->hum;
    humi_property.type = EN_OC_MQTT_PROFILE_VALUE_INT;
    humi_property.nxt = &temp_property;

    temp_property.key = "temp";
    temp_property.value = &report->temp;
    temp_property.type = EN_OC_MQTT_PROFILE_VALUE_INT;
    temp_property.nxt = NULL;

    service.service_id = "device_info";
    service.service_property = &humi_property;
    service.nxt = NULL;

    oc_mqtt_profile_propertyreport(CONFIG_APP_DEVICEID, &service);

    return;
}

//按键扫描
unsigned int lastTickCount;
static void OnButtonPressed(char *arg)
{
    (void)arg;
    unsigned int tickCount = osKernelGetTickCount();
    unsigned int count = tickCount - lastTickCount;
    lastTickCount = tickCount;

    if (count < 50)
    {
        printf("----return\n");
        return;
    }

    enum MotorState nextState = motor_0;

    switch (motor_state)
    {
    case motor_0:
        nextState = motor_1;
        break;
    case motor_1:
        nextState = motor_2;
        break;
    case motor_2:
        nextState = motor_3;
        break;
    case motor_3:
        nextState = motor_0;
        break;
    default:
        break;
    }
    motor_state = nextState;
}

void Key_Motor1()
{
    while (1)
    {
        switch (motor_state)
        {
        case motor_1:
            motor_control(motor_state);
            break;
        case motor_2:
            motor_control(motor_state);
            break;
        case motor_3:
            motor_control(motor_state);
            break;
        case motor_0:
            motor_control(motor_state);
            break;
        default:
            break;
        }
        return NULL;
    }
}

void task_main_entry()
{

    WifiConnect(WIFI_SSID, WIFI_PWD);
    printf("Starting ...\n");
    int rc, count = 0;
    int ret = 0;
    //初始化
    Init();

    IoTGpioRegisterIsrFunc(IOT_GPIO_KEY, IOT_INT_TYPE_EDGE,
                           IOT_GPIO_EDGE_FALL_LEVEL_LOW,
                           OnButtonPressed,
                           NULL);

    //初始化init all
    dtls_al_init();
    mqtt_al_init();
    oc_mqtt_init();

    // config connect_para
    oc_mqtt_profile_connect_t connect_para;
    (void)memset_s(&connect_para, sizeof(connect_para), 0, sizeof(connect_para));

    connect_para.boostrap = 0;
    connect_para.device_id = CONFIG_APP_DEVICEID;
    connect_para.device_passwd = CONFIG_APP_DEVICEPWD;
    connect_para.server_addr = CONFIG_APP_SERVERIP;
    connect_para.server_port = CONFIG_APP_SERVERPORT;
    connect_para.life_time = CONFIG_APP_LIFETIME;
    connect_para.rcvfunc = msg_rcv_callback;
    connect_para.security.type = EN_DTLS_AL_SECURITY_TYPE_NONE;

    // connect to cloud
    ret = oc_mqtt_profile_connect(&connect_para);

    if (ret == 0)
    {
        printf("oc cloud connect success!\n");
    }
    else
    {
        printf("oc cloud connect failed!\n");
    }

    while (1)
    {
        // get temp humi
        float humi;
        float temp;
        SHT3X_ReadMeasurementBuffer(&temp, &humi);

        // report humi temp
        report_t report;
        report.temp = (int)temp;
        report.hum = (int)humi;

        deal_report_msg(&report);

        Key_Motor1();

        // // delay
        osDelay(200);
    }
}
static void oc_MQTTDemo(void)
{
    osThreadAttr_t attr;

    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 10240;
    attr.priority = 24;
    attr.name = "task_main_entry";

    if (osThreadNew((osThreadFunc_t)task_main_entry, NULL, &attr) == NULL)
    {
        printf("[oc_MQTTDemo] Failed to create task_main_entry!\n");
    }
}

APP_FEATURE_INIT(oc_MQTTDemo);